/***************************************************************************
 创建者: 华磊
 开始时间: 2018.8.14
 copyright: (C) 华友高科
 修改说明: (每次有修改就添加一条，带有 修改人，修改时间，修改描述)
 example (1) hualei 2017.5.8 类的具体实现代码编写

 ***************************************************************************/
#include "caniodriver.h"
#include "canioconfig.h"
#include <qdebug.h>

CanIoDriver::CanIoDriver(QString configFileNameIn, int aliasIn,
                             int busNumberIn, int deviceIdIn, CanbusDeviceDriver *canbusDriverIn)
{

    isInitialedOk=false;
    alias=aliasIn;
    busNumber=busNumberIn;
    canbusDriver=canbusDriverIn;
    deviceId=deviceIdIn;
    diNoReceiveCount=0;
    doNoReceiveCount=0;
    initial(configFileNameIn);
}

CanIoDriver::~CanIoDriver()
{
}

int CanIoDriver::startPdoMode()
{
    if( false==isInitialedOk)
    {
        return -1;
    }


    int tmpReturn;
    switch(vendorId)
    {
        case E_VENDOR_ID_AI_KONG:
        {
           return 1;

            break;
        }

    default:
    {
        E_NODE_MANAGE commandIn=E_NODE_MANAGE_START_PDO;
         tmpReturn=canbusDriver->manageNode(deviceId,busNumber,alias,commandIn);
         if(1==tmpReturn)
         {
             return 1;
         }
         else
         {
             return tmpReturn;
         }
         break;
    }
    }

    return -1;
}

int CanIoDriver::sendIoDataRequestCommand()
{
    return 1;
}

int CanIoDriver::updateData()
{
    switch(vendorId)
    {
        case E_VENDOR_ID_NAI_LI_KE:
        {

            break;
        }
        case E_VENDOR_ID_ZONG_KE_ZHI_KONG:
        {

            break;
        }
        case E_VENDOR_ID_SHANGHAI_WEIQUN:
        {
            return processDataFrame_shanghaiWeiqun(diValue_device,doValue_device);
            break;
        }
    case E_VENDOR_ID_SHENG_ZHENG_PU_ZHONG:
    {
        return processDataFrame_shengzhengpuzhong(diValue_device,aiValue_device);
        break;
    }
    }
    return -1;

}

int CanIoDriver::getDeviceAddressInfo(int &aliasOut, int &busNumberOut, int &deviceIdOut)
{
    aliasOut=alias;
    busNumberOut=busNumber;
    deviceIdOut=deviceId;
    return 1;
}

int CanIoDriver::getVendorId()
{
    return vendorId;
}

int CanIoDriver::initial(QString fileName)
{
    qDebug()<<"CanIoDriver initial ,file name="<<fileName;
    canioConfig=new CanIoConfig(fileName);
    if(true==canioConfig->isInitialOkStatus())
    {
        canioConfig->getParameter(regAdd,vendorId);
        canioConfig->getDiDoCount(diCount,doCount,aiCount,aoCount);
        diValue_device.resize(diCount);
        doValue_device.resize(doCount);
        aiValue_device.resize(aiCount);
        aoValue_device.resize(aoCount);
        isInitialedOk=true;
        return 1;

    }
    return -2;
}


bool CanIoDriver::isInitialOkStatus()
{
    return isInitialedOk;
}

int CanIoDriver::getDiDoCount(int &diCounter,int &doCounter,int &aiCounter, int &aoCounter)
{

    if(false==isInitialedOk)
    {
        return -1;
    }
    diCounter=diCount;
    doCounter=doCount;
    aiCounter=aiCount;
    aoCounter=aoCount;

    return 1;
}

int CanIoDriver::writeDo_shanghaiWeiqun(QVector<bool> doValue)
{
    QVector<unsigned char> writeData;
    writeData.resize(2);
    for(int i=0;i<doValue.size();i++)
    {
       if(i<16)
       {
           if(i<8)
           {
                writeData[0]=writeData[0]|doValue[7-i];
                if(7!=i)
                {
                    writeData[0]=writeData[0]<<1;
                }
           }
           else
           {
               writeData[1]=writeData[1]|doValue[15-i];
               if(15!=i)
               {
                   writeData[1]=writeData[1]<<1;
               }
           }


       }
       else
       {
           return -1;
       }
    }
    unsigned int writeFrameId;
    writeFrameId=0x89ab;
    writeFrameId=writeFrameId<<1;
    writeFrameId+=0;
    writeFrameId=writeFrameId<<7;
    writeFrameId+=alias;
    writeFrameId=writeFrameId<<5;
    writeFrameId+=2;
    int keyReturn = canbusDriver->sendData_ext(deviceId, busNumber, writeFrameId, writeData);
    if(1!=keyReturn)
    {
        qDebug()<<"error, writeDo error!";
        return -1;

    }
    return 1;
}

int CanIoDriver::processDataFrame_shanghaiWeiqun(QVector<bool> &diReturn, QVector<bool> &doReturn)
{
    diNoReceiveCount++;
    doNoReceiveCount++;
    QQueue<FrameData> userFrameBuffersOut;
//    canbusDriver->getUserBuffer(userFrameBuffersOut);
    canbusDriver->getUserBuffer(busNumber,userFrameBuffersOut);
    bool isDiReceived=false;
    bool isDoReceived=false;

    unsigned int diFrameId, doFrameId;
    diFrameId=0x89ab;
    diFrameId=diFrameId<<1;
    diFrameId+=1;
    diFrameId=diFrameId<<7;
    diFrameId+=alias;
    diFrameId=diFrameId<<5;
    diFrameId+=3;

    doFrameId=0x89ab;
    doFrameId=doFrameId<<1;
    doFrameId+=1;
    doFrameId=doFrameId<<7;
    doFrameId+=alias;
    doFrameId=doFrameId<<5;
    doFrameId+=2;


    //process data
    for(int i=0;i<userFrameBuffersOut.size();i++)
    {
        //di 获取
        if(userFrameBuffersOut[i].frameId==diFrameId)
        {
            unsigned char tmpChar=userFrameBuffersOut[i].data[0];
            for(int j=0;j<8;j++)
            {
                if(diReturn.size()>=8 && userFrameBuffersOut[i].data.size()>=1)
                {

                    diReturn[j]=tmpChar&1;
                    tmpChar=tmpChar>>1;
                }
            }
            tmpChar=userFrameBuffersOut[i].data[1];
            for(int j=0;j<8;j++)
            {
                if(diReturn.size()>=16 && userFrameBuffersOut[i].data.size()>=2)
                {
                    diReturn[8+j]=tmpChar&1;
                    tmpChar=tmpChar>>1;
                }
            }
            isDiReceived=true;
            diNoReceiveCount=0;

        }
        //do 获取
        else if(userFrameBuffersOut[i].frameId==doFrameId)
        {
            unsigned char tmpChar=userFrameBuffersOut[i].data[0];
            for(int j=0;j<8;j++)
            {
                if(doValue_device.size()>=8 && userFrameBuffersOut[i].data.size()>=1)
                {

                    doReturn[j]=tmpChar&1;
                    tmpChar=tmpChar>>1;
                }
            }
            tmpChar=userFrameBuffersOut[i].data[1];
            for(int j=0;j<8;j++)
            {
                if(doValue_device.size()>=16 && userFrameBuffersOut[i].data.size()>=2)
                {
                    doReturn[8+j]=tmpChar&1;
                    tmpChar=tmpChar>>1;
                }
            }
            isDoReceived=true;
            doNoReceiveCount=0;

        }

        else
        {
//            qDebug()<<"warning, can receive unknow frameId frame!";
            continue;
        }
    }
    if(    diNoReceiveCount<5 || doNoReceiveCount<5)
    {
        return 1;
    }
    else
    {
        return -1;
    }
    return -1;
}

int CanIoDriver::writeDo_shengzhengpuzhong(QVector<bool> doValue, QVector<double> aoValue)
{
    if( false==isInitialedOk)
    {
        return -1;
    }
//    if(true==doValue[3])
//    {
//        qDebug()<<"true==doValue[3]";
//    }

    QVector<unsigned char> writeData(8,0);
//    writeData.resize(8);//初始值可能不为０，resize不会改变原来的内容，新增的元素会被赋予初始值。
    int tmpByte=doValue.size()/8;
    int tmpLoopCount=8*tmpByte;
    if( (doValue.size()%8) > 0)
    {
        tmpLoopCount+=8;
    }
    for(int i=0;i<tmpLoopCount;i++)
    {
       if(i<32)
       {
           if(i<8)
           {
               if(7-i<doValue.size())
               {
                    writeData[0]=writeData[0]|doValue[7-i];

               }
               if(7!=i)
               {
                   writeData[0]=writeData[0]<<1;
               }
           }
           else if(i<16)
           {
               if(15-i+8<doValue.size())
               {
                   writeData[1]=writeData[1]|doValue[15-i+8];

               }
               if(15!=i)
               {
                   writeData[1]=writeData[1]<<1;
               }
           }
           else if(i<24)
           {
               if(23-i+16<doValue.size())
               {
                   writeData[2]=writeData[2]|doValue[23-i+16];

               }
               if(23!=i)
               {
                   writeData[2]=writeData[2]<<1;
               }


           }
           else
           {
               if(31-i+24<doValue.size())
               {
                   writeData[3]=writeData[3]|doValue[31-i+24];

               }
               if(31!=i)
               {
                   writeData[3]=writeData[3]<<1;
               }
           }


       }
       else
       {
           return -1;
       }
    }


    int tmpReturn;
    unsigned int pdoId;

    //pdoId 1 映射ＰＬＣ　Ｄ2０－Ｄ23. D寄存器为１６bit .按照顺序对于Y00-Y07,Y10-Y17,Y20-Y27,Y30-Y37,空闲,空闲,空闲,空闲。
    pdoId=1;

    if(doValue.size()>0)
    {
            writeData[6]=168;//加校验位。
            writeData[7]=0;
            tmpReturn=canbusDriver->sendPdoData(deviceId,busNumber,alias,pdoId,writeData);
    }




//    if(0!= (writeData[0]&8) )
//    {
//        qDebug()<<"0!=writeData[0]&8 writeData="<<writeData;//异响时，这里没有打印
//    }
//    else if(0!= (writeData[0]&16) )
//    {
//        qDebug()<<"0!=writeData[0]&16 writeData="<<writeData;
//    }


    //pdoId 2 映射ＰＬＣ　Ｄ24－Ｄ27　D寄存器为１６bit .AD1,AD2,AD3,空闲
    pdoId=2;
    unsigned short tmpShort;
    for(int i=0;i<aoValue.size();i++)
    {
        tmpShort=aoValue[i];
        writeData[2*i+1]=(tmpShort&0xff00)>>8;
        writeData[2*i]=(tmpShort&0x00ff);//低字节前，高字节后
    }
    if(aoValue.size()>0)
    {
        writeData[6]=217;//加校验位。
        writeData[7]=0;
        tmpReturn=canbusDriver->sendPdoData(deviceId,busNumber,alias,pdoId,writeData);//test与异响无关。
    }

//    //pdoId 3 映射ＰＬＣ　Ｄ28－Ｄ31
//    pdoId=3;
//    tmpReturn=canbusDriver->sendPdoData(deviceId,busNumber,alias,pdoId,writeData);

//    //pdoId 4 映射ＰＬＣ　Ｄ32－Ｄ35
//    pdoId=4;
//    tmpReturn=canbusDriver->sendPdoData(deviceId,busNumber,alias,pdoId,writeData);


    return tmpReturn;
}

int CanIoDriver::processDataFrame_shengzhengpuzhong(QVector<bool> &diReturn, QVector<short> &aiValue)
{
    //bug: 如果设置非自动进入ＯＰ模式，它进不来ＯＰ,pdo数据传输没有工作。
    //如果设置为自动进入Ｏｐ模式，数据有变化就发，没有变不发。

    //pdoId 1 映射ＰＬＣ　Ｄ００－Ｄ03. D寄存器为１６bit .按照顺序对于X00-X07,X10-X17,X20-X27,X30-X37,。
    //pdoId 2 映射ＰＬＣ　Ｄ０4－Ｄ07　D寄存器为１６bit .AI1,AI2,A3。
    //pdoId 3 映射ＰＬＣ　Ｄ０8－Ｄ011
    //pdoId 4 映射ＰＬＣ　Ｄ12－Ｄ15　Ｄ12作为心跳


    QVector<unsigned int> nodeIdOut;
    QVector<unsigned int> pdoIdOut;
    QVector<QVector<unsigned char> > dataListOut;
    if(0==busNumber)
    {
            canbusDriver->getPdoData_ch1(nodeIdOut,pdoIdOut,dataListOut);
    }
    else if(1==busNumber)
    {
            canbusDriver->getPdoData_ch2(nodeIdOut,pdoIdOut,dataListOut);
    }
    else
    {
        qDebug()<<"error, busNumber invalid,busNumber="<<busNumber;
        return -1;
    }

//    qDebug()<<"getPdoData----------------------------------*********************************";
//    qDebug()<<"getPdoData nodeIdOut="<<nodeIdOut;
//    qDebug()<<"getPdoData pdoIdOut="<<pdoIdOut;
//    qDebug()<<"getPdoData dataListOut="<<dataListOut;

    bool isReceived=false;


    for(int i=0;i<nodeIdOut.size();i++)
    {
        if(alias==nodeIdOut[i])
        {
            if(1==pdoIdOut[i])
            {
                if(8==dataListOut[i].size())
                {
                    //di
                    unsigned char tmpChar;
                    for(int j=0;j<64;j++)
                    {
                        int byteIndex=j/8;
                        if(j%8==0)
                        {
                            tmpChar=dataListOut[i][byteIndex];
                        }

                        if(diReturn.size()>j)
                        {
                            diReturn[j]=tmpChar&1;
                            tmpChar=tmpChar>>1;
                        }
                    }

                }
            }
            else if(2==pdoIdOut[i])
            {
                if(8==dataListOut[i].size())
                {
                    for(int j=0;j<4;j++)
                    {

                        if(aiValue.size()>j)
                        {
                            aiValue[j]=dataListOut[i][2*j+1];
                            aiValue[j]=aiValue[j]<<8;
                            aiValue[j]=aiValue[j]|dataListOut[i][2*j];//低字节前，高字节后
                        }
                    }


                }
                isReceived=true;//20ms心跳使用该通道。可能丢帧，如果输入跳变才发送一直，可能导致软件没有检测到变换，所以要一直发。

            }
            else if(3==pdoIdOut[i])
            {

            }
            else if(4==pdoIdOut[i])
            {

            }
        }

    }



    return isReceived;

}

int CanIoDriver::readAllDi(QVector<bool> & diReturn)
{
    if( false==isInitialedOk || diReturn.size()>diCount)
    {
        diReturn.resize(0);
        return -1;
    }

    diReturn.resize(diCount);
    return readDi(diReturn);
}

int CanIoDriver::readAllAi(QVector<double> &aiReturn)
{
    if( false==isInitialedOk || aiReturn.size()>aiCount)
    {
        aiReturn.resize(0);
        return -1;
    }

    aiReturn.resize(aiCount);
    return readAi(aiReturn);
}


int CanIoDriver::readDi(QVector<bool> & diReturn)
{

    if( false==isInitialedOk || diReturn.size()>diCount)
    {
        return -1;
    }

    diReturn=diValue_device;

    return 1;
}

int CanIoDriver::readAi(QVector<double> &aiReturn)
{
    if( false==isInitialedOk || aiReturn.size()>aiCount)
    {
        return -1;
    }

    for(int i=0;i<aiReturn.size();i++)
    {
        aiReturn[i]=aiValue_device[i];
    }


    return 1;
}

int CanIoDriver::readDo(QVector<bool> & doReturn)
{

    if( false==isInitialedOk|| doReturn.size()>doCount)
    {
        return -1;
    }
    doReturn=doValue_device;
    return -1;
}


int CanIoDriver::writeDo(QVector<bool> doValue,QVector<double> aoValue)
{

    if( false==isInitialedOk|| doValue.size()>doCount ||aoValue.size()>aoCount)
    {
        return -1;
    }


    switch(vendorId)
    {
    case E_VENDOR_ID_NAI_LI_KE:
    {

        break;
    }
    case E_VENDOR_ID_ZONG_KE_ZHI_KONG:
    {

       break;
    }
    case E_VENDOR_ID_SHANGHAI_WEIQUN:
    {
       return writeDo_shanghaiWeiqun(doValue);
       break;
    }
    case E_VENDOR_ID_SHENG_ZHENG_PU_ZHONG:
    {
       return writeDo_shengzhengpuzhong(doValue,aoValue);
       break;
    }
    }

    return -1;
}

